/**
 * Simple event emitter implementation
 */

import type { EventEmitter, ComfyUIEvent, EventListener } from '../types';

/**
 * Simple event emitter for ComfyUI events
 */
export class SimpleEventEmitter implements EventEmitter {
  private readonly listeners = new Map<string, Set<EventListener>>();

  /**
   * Adds an event listener
   * @param eventType - Event type to listen for
   * @param listener - Event listener function
   */
  on<T extends ComfyUIEvent>(eventType: T['type'], listener: EventListener<T>): void {
    if (!this.listeners.has(eventType)) {
      this.listeners.set(eventType, new Set());
    }
    this.listeners.get(eventType)!.add(listener as EventListener);
  }

  /**
   * Removes an event listener
   * @param eventType - Event type
   * @param listener - Event listener function to remove
   */
  off<T extends ComfyUIEvent>(eventType: T['type'], listener: EventListener<T>): void {
    const eventListeners = this.listeners.get(eventType);
    if (eventListeners) {
      eventListeners.delete(listener as EventListener);
      if (eventListeners.size === 0) {
        this.listeners.delete(eventType);
      }
    }
  }

  /**
   * Emits an event to all listeners
   * @param event - Event to emit
   */
  emit<T extends ComfyUIEvent>(event: T): void {
    const eventListeners = this.listeners.get(event.type);
    if (eventListeners) {
      for (const listener of eventListeners) {
        try {
          listener(event);
        } catch (error) {
          console.error('Error in event listener:', error);
        }
      }
    }
  }

  /**
   * Removes all listeners for a specific event type
   * @param eventType - Event type to clear (optional, clears all if not provided)
   */
  removeAllListeners(eventType?: string): void {
    if (eventType) {
      this.listeners.delete(eventType);
    } else {
      this.listeners.clear();
    }
  }

  /**
   * Gets the number of listeners for an event type
   * @param eventType - Event type
   * @returns Number of listeners
   */
  listenerCount(eventType: string): number {
    return this.listeners.get(eventType)?.size || 0;
  }

  /**
   * Gets all event types that have listeners
   * @returns Array of event types
   */
  eventNames(): string[] {
    return Array.from(this.listeners.keys());
  }
}
